package org.jeecg.modules.consumptionElectricity.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.consumptionElectricity.entity.ConsumptionElectricity;
import org.jeecg.modules.consumptionElectricity.entity.ElectricitySelectDTO;
import org.jeecg.modules.consumptionElectricity.entity.TrackingDTO;
import org.jeecg.modules.consumptionElectricity.mapper.ConsumptionElectricityMapper;
import org.jeecg.modules.consumptionElectricity.service.IConsumptionElectricityService;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.time.OffsetDateTime;
import java.util.*;

/**
 * @Description: 电能能耗
 * @Author: jeecg-boot
 * @Date: 2023-06-20
 * @Version: V1.0
 */
@Service
@Slf4j
public class ConsumptionElectricityServiceImpl extends ServiceImpl<ConsumptionElectricityMapper, ConsumptionElectricity> implements IConsumptionElectricityService {

    @Override
    public List<ConsumptionElectricity> selectByTime(@NotNull ElectricitySelectDTO selectDTO) {
        QueryWrapper<ConsumptionElectricity> wrapper = getConsumptionElectricityQueryWrapper(selectDTO);
        if (selectDTO.getDept() != null){
            wrapper.eq("dept", selectDTO.getDept());
        }
        if (selectDTO.getProduct() != null){
            wrapper.eq("product", selectDTO.getProduct());
        }
        if (selectDTO.getDevice() != null){
            wrapper.eq("device", selectDTO.getDevice());
        }
        if ("date".equals(selectDTO.getDatePickerType())) {
            wrapper.select("sum(consumption) as consumption", "year", "month", "day")
                    .groupBy("month", "year", "day").orderByAsc("year*1", "month*1", "day*1");
        } else if ("datetime".equals(selectDTO.getDatePickerType())) {
            wrapper.select("sum(consumption) as consumption", "year", "month", "day", "hour")
                    .groupBy("month", "year", "day", "hour").orderByAsc("year*1", "month*1", "day*1", "hour*1");
        } else {
            wrapper.select("sum(consumption) as consumption", "year", "month")
                    .groupBy("month", "year").orderByAsc("year*1", "month*1");
        }
        return baseMapper.selectList(wrapper);
    }

    @Override
    public List<ConsumptionElectricity> selectCarbonEmission(ElectricitySelectDTO selectDTO) {
        QueryWrapper<ConsumptionElectricity> wrapper = getConsumptionElectricityQueryWrapper(selectDTO);
        if ("date".equals(selectDTO.getDatePickerType())) {
            wrapper.select("sum(carbon_emission) as carbonEmission", "product", "year", "month", "day")
                    .groupBy("month", "year", "day", "product").orderByAsc("year*1", "month*1", "day*1");
        } else if ("datetime".equals(selectDTO.getDatePickerType())) {
            wrapper.select("sum(carbon_emission) as carbonEmission", "year", "month", "day", "hour")
                    .groupBy("month", "year", "day", "hour").orderByAsc("year*1", "month*1", "day*1", "hour*1");
        } else {
            wrapper.select("sum(carbon_emission) as carbonEmission", "product", "year", "month")
                    .groupBy("month", "year", "product").orderByAsc("year*1", "month*1");
        }
        return baseMapper.selectList(wrapper);
    }

    @Override
    public List<ConsumptionElectricity> selectProductConsumption(ElectricitySelectDTO selectDTO) {
        QueryWrapper<ConsumptionElectricity> wrapper = getConsumptionElectricityQueryWrapper(selectDTO);
        wrapper.eq("production_line", selectDTO.getProductionLine());
        if ("date".equals(selectDTO.getDatePickerType())) {
            wrapper.select("sum(consumption) as consumption", "production_line", "year", "month", "day")
                    .groupBy("month", "year", "day", "production_line").orderByAsc("year*1", "month*1", "day*1");
        } else if ("datetime".equals(selectDTO.getDatePickerType())) {
            wrapper.orderByAsc("date");
        } else {
            wrapper.select("sum(consumption) as consumption", "production_line", "year", "month")
                    .groupBy("month", "year", "production_line").orderByAsc("year*1", "month*1");
        }
        return baseMapper.selectList(wrapper);
    }

    @NotNull
    public static QueryWrapper<ConsumptionElectricity> getConsumptionElectricityQueryWrapper(ElectricitySelectDTO selectDTO) {
        if (selectDTO.getStartTime() == null || selectDTO.getEndTime() == null) {
            throw new JeecgBootException("服务器忙,请稍后再试...");
        }
        QueryWrapper<ConsumptionElectricity> wrapper = new QueryWrapper<>();
        Date start = Date.from(selectDTO.getStartTime().toInstant());
        Date end = Date.from(selectDTO.getEndTime().toInstant());
        wrapper.between("date", start, end);
        return wrapper;
    }

    @Override
    public List<Map<String, Object>> getAllGroupByDept() {
        QueryWrapper<ConsumptionElectricity> wrapper = new QueryWrapper<>();
        wrapper.select("sum(consumption) as sum_value", "dept").groupBy("dept").having("sum_value > 0");
        return baseMapper.selectMaps(wrapper);
    }

    @Override
    public Map<String, Object> getIndex() {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        QueryWrapper<ConsumptionElectricity> wrapper = new QueryWrapper<>();
        wrapper.select("consumption").eq("year", year).eq("month", month);
        Map<String, Object> map = new HashMap<>();
        List<Map<String, Object>> list = baseMapper.selectMaps(wrapper);
        list.get(0).put("type", "电");
        map.put("data", list);
        return map;
    }

    /**
     * 获取某天的能耗数据
     *
     * @param year  年
     * @param month 月
     * @param day   日
     * @return
     */
    @Override
    public List<Map<String, Object>> getDayConsumption(int year, int month, int day, int hour) {
        QueryWrapper<ConsumptionElectricity> wrapper = new QueryWrapper<>();
        wrapper.select("sum(consumption) consumption", "year", "month", "day", "hour", "dept")
                .eq("year", year).eq("month", month).eq("day", day).eq("hour", hour)
                .groupBy("month", "year", "day", "hour", "dept");
        return baseMapper.selectMaps(wrapper);
    }

    @Override
    public List<List<ConsumptionElectricity>> getTracking(TrackingDTO trackingDTO) {
        List<String> labels = trackingDTO.getLabels();
        if (labels.size() == 0){
            return null;
        }
        OffsetDateTime selectedDate = trackingDTO.getSelectedDate();
        String pickerType = trackingDTO.getPickerType();
        String year = String.valueOf(selectedDate.getYear());
        String month = String.valueOf(selectedDate.getMonth().getValue());
        String dayOfMonth = String.valueOf(selectedDate.getDayOfMonth());
        QueryWrapper<ConsumptionElectricity> wrapper = new QueryWrapper<>();
        wrapper.eq("year", year);
        if ("year".equals(pickerType)){
            wrapper.select("sum(consumption) consumption","month","dept","product","production_line")
                    .groupBy("month","dept","product","production_line").orderByAsc("month*1");
        }
        if ("month".equals(pickerType)){
            wrapper.select("sum(consumption) consumption","day","dept","product","production_line").eq("month", month)
                    .groupBy("day","dept","product","production_line").orderByAsc("day*1");
        }
        if ("date".equals(pickerType)) {
            wrapper.select("sum(consumption) consumption","hour","dept","product","production_line")
                    .eq("month", month).eq("day", dayOfMonth)
                    .groupBy("hour","dept","product","production_line").orderByAsc("hour*1");
        }
        wrapper.and(w->{w.in("dept", labels).or().in("product", labels).or().in("production_line", labels);});
        List<ConsumptionElectricity> list = baseMapper.selectList(wrapper);
        List<ConsumptionElectricity> listByDept = new LinkedList<>();
        List<ConsumptionElectricity> listByProduct = new LinkedList<>();
        List<ConsumptionElectricity> listByProductionLine = new LinkedList<>();
        for (String label : labels){
            for (ConsumptionElectricity ce : list){
                if (label.equals(ce.getDept())){
                    listByDept.add(ce);
                }
                if (label.equals(ce.getProduct())){
                    listByProduct.add(ce);
                }
                if (label.equals(ce.getProductionLine())){
                    listByProductionLine.add(ce);
                }
            }
        }
        List<List<ConsumptionElectricity>> list1 = new LinkedList<>();
        list1.add(listByDept);
        list1.add(listByProduct);
        list1.add(listByProductionLine);
        return list1;
    }

}
